// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UIAdmin.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Extensions.Admin.UI.Forms
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Windows.Forms;

    using Framework;

    using Org.OpenTrader.Framework.Entities;
    using Org.OpenTrader.Framework.Enums;
    using Org.OpenTrader.Framework.Events;
    using Org.OpenTrader.Framework.LiveObjects;
    using Org.OpenTrader.Framework.LiveObjects.Interfaces;
    using Org.OpenTrader.Framework.UI.Forms;

    #endregion

    /// <summary>
    /// The uiot adm.
    /// </summary>
    public partial class UIAdmin : UIRootControl
    {
        #region Constants and Fields

        /// <summary>
        /// The containersCache.
        /// </summary>
        private LiveObjectContainerCache containersCache;

        /// <summary>
        /// The dbContextByName.
        /// </summary>
        private IDictionary<string, DBExecutionContext> dbContextByName;

        /// <summary>
        /// The dbContextCurrent.
        /// </summary>
        private DBExecutionContext dbContextCurrent;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UIAdmin"/> class.
        /// </summary>
        public UIAdmin()
        {
            this.InitializeComponent();

            // Singleton<LiveObjectsRegistry>.Instance.LiveObjectsEventCB += OnLiveObjectsEvent;
            this.ExecutionContextsRefreshList();
            this.ResourcesRefreshAll();
        }

        #endregion

        #region Methods

        /// <summary>
        /// The execution contexts_ build node name.
        /// </summary>
        /// <param name="dbLiveObject">
        /// The dbLiveObject.
        /// </param>
        /// <returns>
        /// The execution contexts_ build node name.
        /// </returns>
        private static string ExecutionContextsBuildNodeName(DBLiveObject dbLiveObject)
        {
            if (dbLiveObject.Label != null)
            {
                return string.Format("{0} ({1})", dbLiveObject.Name, dbLiveObject.Label);
            }

            return dbLiveObject.Name;
        }

        /// <summary>
        /// The resources_ build tooltip.
        /// </summary>
        /// <param name="dbResource">
        /// The dbResource.
        /// </param>
        /// <returns>
        /// The resources_ build tooltip.
        /// </returns>
        private static string ResourcesBuildTooltip(DBResource dbResource)
        {
            return string.Format(
                "{0,-12} {1,40}\n{2,-12} {3,40}\n{4,-12} {5,40}\n", 
                "name", 
                dbResource.Name, 
                "TimeStamp", 
                dbResource.TimeStamp, 
                "Size", 
                dbResource.Content.Length + " bytes");
        }

        /// <summary>
        /// The execution contexts_ build application node_ existing application.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="dbApplication">
        /// The dbApplication.
        /// </param>
        /// <param name="runtimeNode">
        /// The runtimeNode.
        /// </param>
        private void ExecutionContextsBuildApplicationNodeExistingApplication(DBExecutionContext ctx, DBLiveObject dbApplication, TreeNode runtimeNode)
        {
            var nodeApplication = new TreeNode(ExecutionContextsBuildNodeName(dbApplication));
            nodeApplication.ContextMenu = new ContextMenu();
            nodeApplication.ToolTipText = this.ExecutionContextsBuildLiveObjectDescriptorTooltip(dbApplication);

            var menuiteEditNameMemo = new MenuItem(
                "Edit Label ...", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbApplication = (sender as MenuItem).Tag as DBLiveObject;
                        this.ExecutionContextsEditMemo(myDbApplication);
                    });
            menuiteEditNameMemo.Tag = dbApplication;
            nodeApplication.ContextMenu.MenuItems.Add(menuiteEditNameMemo);

            var menuiteEditConfig = new MenuItem(
                "Edit Configuration ...", 
                delegate(object sender, EventArgs args)
                    {
                        var parameters = (sender as MenuItem).Tag as object[];
                        var myDbApplication = parameters[0] as DBLiveObject;
                        var mySchema = parameters[1] as string;
                        UIConfigurationEditor.EditConfiguration(
                            dbApplication.DBConfigurationID, mySchema, this.containersCache.GetContainer(dbApplication.DBContainer.ID));

                        // Refresh
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteEditConfig.Tag = new object[] { dbApplication, dbApplication.ClassFullTypeName };
            nodeApplication.ContextMenu.MenuItems.Add(menuiteEditConfig);

            // if (schema == null)
            // {
            // menuiteEditConfig.Enabled = false;
            // }
            nodeApplication.ContextMenu.MenuItems.Add(new MenuItem("-"));

            var menuiteChooseClass = new MenuItem(
                "Delete Application", 
                delegate(object sender, EventArgs args)
                    {
                        // Get back the related application
                        var myDbApplication = (sender as MenuItem).Tag as DBLiveObject;

                        DBLiveObjectHelpers.Delete(myDbApplication);

                        // Refresh
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteChooseClass.Tag = dbApplication;
            nodeApplication.ContextMenu.MenuItems.Add(menuiteChooseClass);

            // Load services LiveObjects
            dbApplication.DBLiveObject1.Load();
            var dbServices = dbApplication.DBLiveObject1.ToArray();
            foreach (var dbService in dbServices)
            {
                var nodeService = new TreeNode(ExecutionContextsBuildNodeName(dbService));
                nodeService.ContextMenu = new ContextMenu();
                nodeService.ToolTipText = this.ExecutionContextsBuildLiveObjectDescriptorTooltip(dbService);

                if (dbService.Location == null)
                {
                    this.ExecutionContextsBuildServiceNodeNewDescriptor(ctx, dbService, nodeService);
                }
                else if (dbService.Location.Equals("L"))
                {
                    this.ExecutionContextsBuildServiceNodeExistingLocalDescriptor(ctx, dbService, nodeService);
                }
                else if (dbService.Location.Equals("R"))
                {
                    this.ExecutionContextsBuildServiceNodeExistingRemoteDescriptor(ctx, dbService, nodeService);
                }

                dbService.DBLiveObject1.Load();
                var dbPlugins = dbService.DBLiveObject1.ToArray();
                foreach (var dbPlugin in dbPlugins)
                {
                    var nodePlugin = new TreeNode(ExecutionContextsBuildNodeName(dbPlugin));
                    nodePlugin.ContextMenu = new ContextMenu();
                    nodePlugin.ToolTipText = this.ExecutionContextsBuildLiveObjectDescriptorTooltip(dbPlugin);

                    this.ExecutionContextsBuildPluginNodeExistingLocalDescriptor(ctx, dbPlugin, dbService, nodePlugin);

                    nodeService.Nodes.Add(nodePlugin);
                }

                nodeApplication.Nodes.Add(nodeService);
            }

            runtimeNode.Nodes.Add(nodeApplication);
        }

        /// <summary>
        /// The execution contexts_ build application node_ new application.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="runtimeNode">
        /// The runtimeNode.
        /// </param>
        private void ExecutionContextsBuildApplicationNodeNewApplication(DBExecutionContext ctx, TreeNode runtimeNode)
        {
            var menuiteChooseClass = new MenuItem(
                "Create Application ...", 
                delegate(object sender, EventArgs args)
                    {
                        // Create an application live object
                        var dbApplication = DBLiveObject.CreateDBLiveObject(
                            Guid.NewGuid(), Guid.NewGuid(), ctx.ID, "A", typeof(IApplication).FullName, ctx.Name);

                        // Parameterize it using dedicated control
                        var ctrl = new UILiveObjectDescriptorLocal("A", typeof(IApplication).FullName, dbApplication, this.containersCache);

                        // Auto containing form
                        var form = ctrl.CreateContainingForm("Application Setup", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);

                        // Wait until close
                        form.Visibility = EUIFormVisibility.ShowDialog;

                        // If the data is valid
                        if (ctrl.SelectedTypeName != null)
                        {
                            // Attributes of the chosen class
                            var i = 0;
                            foreach (var v in ctrl.SelectedTypeNameAttributes)
                            {
                                // Create a service live object for each service of the application (from attributes)
                                if (v is ServiceAttribute)
                                {
                                    var serviceAttribute = v as ServiceAttribute;

                                    var dbService = DBLiveObject.CreateDBLiveObject(
                                        Guid.NewGuid(), Guid.NewGuid(), ctx.ID, "S", serviceAttribute.Interface, serviceAttribute.Name);

                                    dbService.Name = serviceAttribute.Name;
                                    dbService.ServicePluginInterfaceTypeName = serviceAttribute.PluginInterface;
                                    dbApplication.DBLiveObject1.Add(dbService);
                                }

                                i++;
                            }

                            // This is the specialized interface type of application
                            dbApplication.InterfaceFullTypeName = string.Join(";", ctrl.SelectedTypeNameImplementedInterfaceName);

                            // Give a name to begin with
                            dbApplication.Name = ctrl.SelectedTypeShortName;

                            // Add the object (and its children services) to the store
                            Singleton<DB>.Instance.Entities.AddToDBLiveObject(dbApplication);

                            // Save changes
                            Singleton<DB>.Instance.Commit();

                            // Refresh
                            this.ExecutionContextsRefreshCurrent();
                        }
                    });
            runtimeNode.ContextMenu.MenuItems.Add(menuiteChooseClass);
        }

        /// <summary>
        /// The execution contexts_ build container resource tooltip.
        /// </summary>
        /// <param name="dbResource">
        /// The dbResource.
        /// </param>
        /// <returns>
        /// The execution contexts_ build container resource tooltip.
        /// </returns>
        private string ExecutionContextsBuildContainerResourceTooltip(DBContainerResource dbResource)
        {
            // Descriptor is ok
            dbResource.DBResourceReference.Load();
            return string.Format("From {0}", dbResource.DBResource.Directory);
        }

        /// <summary>
        /// The execution contexts_ build live object descriptor tooltip.
        /// </summary>
        /// <param name="dbLiveObject">
        /// The dbLiveObject.
        /// </param>
        /// <returns>
        /// The execution contexts_ build live object descriptor tooltip.
        /// </returns>
        private string ExecutionContextsBuildLiveObjectDescriptorTooltip(DBLiveObject dbLiveObject)
        {
            // Doesn't have a descriptor yet
            if (dbLiveObject.Location == null)
            {
                return "No descriptor was created yet";
            }

            // Local
            if (dbLiveObject.Location.CompareTo("L") == 0)
            {
                // Fetch associated container info
                dbLiveObject.DBContainerReference.Load();

                // No container means not yet edited
                if (dbLiveObject.DBContainer == null)
                {
                    return "Local descriptor is not yet configured";
                }

                string containerHelptext;
                if (!dbLiveObject.DBContainer.IsStrong.HasValue)
                {
                    containerHelptext = "Default AppDomain within main process";
                }
                else
                {
                    if (dbLiveObject.DBContainer.IsStrong.Value)
                    {
                        containerHelptext = "Default AppDomain within an external process";
                    }
                    else
                    {
                        containerHelptext = string.Format("AppDomain '{0}' within main process", dbLiveObject.DBContainer.Name);
                    }
                }

                // Descriptor is ok
                var result = string.Format(
                    "** Local LiveObject Descriptor **\n\n{0}{1}{2}\n{3}{4}{5}\n{6}{7}{8}\n{9}{10}{11}\n{12}{13}{14}", 
                    "Name", 
                    this.Tabs("Name"), 
                    dbLiveObject.Name, 
                    "Implements", 
                    this.Tabs("Implements"), 
                    dbLiveObject.InterfaceFullTypeName, 
                    "Container", 
                    this.Tabs("Container"), 
                    dbLiveObject.DBContainer.Name + " (" + containerHelptext + ")", 
                    "Implementor", 
                    this.Tabs("Implementor"), 
                    dbLiveObject.ClassFullTypeName, 
                    "ListenURL", 
                    this.Tabs("ListenURL"), 
                    dbLiveObject.ListenURL != null ? dbLiveObject.ListenURL : "Don't Listen");

                // Local, try to read the configuration if any
                if (dbLiveObject.DBContainer != null)
                {
                    var container = this.containersCache.GetContainer(dbLiveObject.DBContainer.ID);

                    var configuration = DBConfigurationHelpers.LoadConfiguration(dbLiveObject.DBConfigurationID, dbLiveObject.ClassFullTypeName, container);

                    if (configuration != null)
                    {
                        result += "\n\n** Configuration **\n\n";
                        foreach (var field in configuration.ConfigurationSchema.Fields)
                        {
                            // object o = null;
                            // Devel.NoThrow(delegate()
                            // {
                            // o = ;
                            // });
                            result += string.Format("{0}{1}{2}\n", field, this.Tabs(field), configuration[field]);
                        }
                    }
                }

                return result;
            }

            // Remote
            if (dbLiveObject.Location.CompareTo("R") == 0)
            {
                // No URL means not yet edited
                if (dbLiveObject.URL == null)
                {
                    return "Remote descriptor is not yet configured";
                }

                // Descriptor is ok
                return string.Format(
                    "** Remote LiveObject Descriptor **\n\n{0}\t\t{1}\n{2}\t{3}\n{4}\t\t{5}", 
                    "Name", 
                    dbLiveObject.Name, 
                    "Interface", 
                    dbLiveObject.InterfaceFullTypeName, 
                    "URL", 
                    dbLiveObject.URL);
            }

            return null;
        }

        /// <summary>
        /// The execution contexts_ build plugin node_ existing local descriptor.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="dbPlugin">
        /// The dbPlugin.
        /// </param>
        /// <param name="dbService">
        /// The dbService.
        /// </param>
        /// <param name="pluginNode">
        /// The pluginNode.
        /// </param>
        private void ExecutionContextsBuildPluginNodeExistingLocalDescriptor(DBExecutionContext ctx, 
                                                                             DBLiveObject dbPlugin, 
                                                                             DBLiveObject dbService, 
                                                                             TreeNode pluginNode)
        {
            var menuiteEditNameMemo = new MenuItem(
                "Edit Label ...", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbPlugin = (sender as MenuItem).Tag as DBLiveObject;
                        this.ExecutionContextsEditMemo(myDbPlugin);
                    });
            menuiteEditNameMemo.Tag = dbPlugin;
            pluginNode.ContextMenu.MenuItems.Add(menuiteEditNameMemo);

            var menuiteEditConfig = new MenuItem(
                "Edit Configuration ...", 
                delegate(object sender, EventArgs args)
                    {
                        var parameters = (sender as MenuItem).Tag as object[];
                        var myDbPlugin = parameters[0] as DBLiveObject;
                        var mySchema = parameters[1] as string;
                        UIConfigurationEditor.EditConfiguration(
                            myDbPlugin.DBConfigurationID, mySchema, this.containersCache.GetContainer(myDbPlugin.DBContainer.ID));

                        // Refresh
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteEditConfig.Tag = new object[] { dbPlugin, dbPlugin.ClassFullTypeName };
            pluginNode.ContextMenu.MenuItems.Add(menuiteEditConfig);

            // if (schema == null)
            // {
            // menuiteEditConfig.Enabled = false;
            // }
            pluginNode.ContextMenu.MenuItems.Add(new MenuItem("-"));

            var menuiteDeletePlugin = new MenuItem(
                "Delete Plugin", 
                delegate(object sender, EventArgs args)
                    {
                        var parameters = (sender as MenuItem).Tag as object[];
                        var myDbPlugin = parameters[0] as DBLiveObject;
                        var myDbService = parameters[1] as DBLiveObject;

                        DBLiveObjectHelpers.Delete(myDbPlugin);

                        // Refresh view
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteDeletePlugin.Tag = new object[] { dbPlugin, dbService };
            pluginNode.ContextMenu.MenuItems.Add(menuiteDeletePlugin);
        }

        /// <summary>
        /// The execution contexts_ build service node_ existing local descriptor.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="dbService">
        /// The dbService.
        /// </param>
        /// <param name="serviceNode">
        /// The serviceNode.
        /// </param>
        private void ExecutionContextsBuildServiceNodeExistingLocalDescriptor(DBExecutionContext ctx, DBLiveObject dbService, TreeNode serviceNode)
        {
            serviceNode.SelectedImageIndex = 2;
            serviceNode.ImageIndex = 2;

            var menuiteEditNameMemo = new MenuItem(
                "Edit Label ...", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;
                        this.ExecutionContextsEditMemo(myDbService);
                    });
            menuiteEditNameMemo.Tag = dbService;
            serviceNode.ContextMenu.MenuItems.Add(menuiteEditNameMemo);

            var menuiteEditDescriptor = new MenuItem(
                "Edit Local Descriptor ...", 
                delegate(object sender, EventArgs args)
                    {
                        // Related service
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;

                        var ctrl = new UILiveObjectDescriptorLocal("S", myDbService.InterfaceFullTypeName, myDbService, this.containersCache);

                        var form = ctrl.CreateContainingForm(myDbService.Name, EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);
                        form.Visibility = EUIFormVisibility.ShowDialog;

                        // Data is valid
                        if (ctrl.SelectedTypeName != null)
                        {
                            // Save changes
                            Singleton<DB>.Instance.Commit();

                            // Refresh
                            this.ExecutionContextsRefreshCurrent();
                        }
                    });
            menuiteEditDescriptor.Tag = dbService;
            serviceNode.ContextMenu.MenuItems.Add(menuiteEditDescriptor);

            if (dbService.DBContainer != null)
            {
                var menuiteEditConfig = new MenuItem(
                    "Edit Configuration ...", 
                    delegate(object sender, EventArgs args)
                        {
                            var parameters = (sender as MenuItem).Tag as object[];
                            var myDbService = parameters[0] as DBLiveObject;
                            var myTypename = parameters[1] as string;
                            UIConfigurationEditor.EditConfiguration(
                                myDbService.DBConfigurationID, myTypename, this.containersCache.GetContainer(myDbService.DBContainer.ID));

                            // Refresh
                            this.ExecutionContextsRefreshCurrent();
                        });
                menuiteEditConfig.Tag = new object[] { dbService, dbService.ClassFullTypeName };
                serviceNode.ContextMenu.MenuItems.Add(menuiteEditConfig);

                // if (schema == null)
                // {
                // menuiteEditConfig.Enabled = false;
                // }
            }

            // "Add Plugin ..." Only for local services (with descriptor already set, thus with a non null container)
            if (dbService.ServicePluginInterfaceTypeName != null)
            {
                var addPluginInstance = new MenuItem(
                    "Add Plugin ...", 
                    (object sender, EventArgs args) =>
                        {
                            // Selected
                            var myDbService = (sender as MenuItem).Tag as DBLiveObject;

                            var myDbPlugin = DBLiveObject.CreateDBLiveObject(
                                Guid.NewGuid(), Guid.NewGuid(), ctx.ID, "P", myDbService.ServicePluginInterfaceTypeName, string.Empty);
                            myDbPlugin.Location = "L";

                            // Parameterize it using dedicated control
                            var ctrl = new UILiveObjectDescriptorLocal("P", myDbService.ServicePluginInterfaceTypeName, myDbPlugin, this.containersCache);

                            // Auto containing form
                            var form = ctrl.CreateContainingForm("Plugin Setup", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);

                            // Wait until close
                            form.Visibility = EUIFormVisibility.ShowDialog;

                            // If the data is valid
                            if (ctrl.SelectedTypeName != null)
                            {
                                myDbPlugin.Name = ctrl.SelectedTypeShortName;
                                myDbPlugin.Label = ctrl.SelectedTypeShortName;
                                myDbService.DBLiveObject1.Add(myDbPlugin);

                                // Save changes
                                var n = Singleton<DB>.Instance.Commit();

                                // Refresh view
                                this.ExecutionContextsRefreshCurrent();
                            }
                        });
                addPluginInstance.Tag = dbService;
                if (dbService.DBContainer == null)
                {
                    addPluginInstance.Enabled = false;
                }

                serviceNode.ContextMenu.MenuItems.Add(addPluginInstance);
            }
        }

        /// <summary>
        /// The execution contexts_ build service node_ existing remote descriptor.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="dbService">
        /// The dbService.
        /// </param>
        /// <param name="serviceNode">
        /// The serviceNode.
        /// </param>
        private void ExecutionContextsBuildServiceNodeExistingRemoteDescriptor(DBExecutionContext ctx, DBLiveObject dbService, TreeNode serviceNode)
        {
            serviceNode.SelectedImageIndex = 3;
            serviceNode.ImageIndex = 3;

            var menuiteEditNameMemo = new MenuItem(
                "Edit Label ...", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;
                        this.ExecutionContextsEditMemo(myDbService);
                    });
            menuiteEditNameMemo.Tag = dbService;
            serviceNode.ContextMenu.MenuItems.Add(menuiteEditNameMemo);

            var menuiteEditDescriptor = new MenuItem(
                "Edit Remote Descriptor ...", 
                delegate(object sender, EventArgs args)
                    {
                        // Related service
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;

                        // Configure this remote service using that control
                        var ctrl = new UILiveObjectDescriptorRemote(myDbService.InterfaceFullTypeName, myDbService);

                        // Create a form to display the control
                        var form = ctrl.CreateContainingForm(myDbService.Name, EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);

                        // Blocking
                        form.Visibility = EUIFormVisibility.ShowDialog;

                        // Data is valid
                        if (ctrl.SelectedURL != null)
                        {
                            // Save changes
                            var n = Singleton<DB>.Instance.Commit();

                            // Refresh
                            this.ExecutionContextsRefreshCurrent();
                        }
                    });
            menuiteEditDescriptor.Tag = dbService;
            serviceNode.ContextMenu.MenuItems.Add(menuiteEditDescriptor);
        }

        /// <summary>
        /// The execution contexts_ build service node_ new descriptor.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <param name="dbService">
        /// The dbService.
        /// </param>
        /// <param name="serviceNode">
        /// The serviceNode.
        /// </param>
        private void ExecutionContextsBuildServiceNodeNewDescriptor(DBExecutionContext ctx, DBLiveObject dbService, TreeNode serviceNode)
        {
            var menuiteCreateDescriptor = new MenuItem("Create Descriptor");
            serviceNode.ContextMenu.MenuItems.Add(menuiteCreateDescriptor);

            var menuiteCreateLocalDescriptor = new MenuItem(
                "Local", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;
                        myDbService.Location = "L";
                        var n = Singleton<DB>.Instance.Commit();

                        // Refresh
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteCreateLocalDescriptor.Tag = dbService;

            menuiteCreateDescriptor.MenuItems.Add(menuiteCreateLocalDescriptor);

            var menuiteCreateRemoteDescriptor = new MenuItem(
                "Remote", 
                delegate(object sender, EventArgs args)
                    {
                        var myDbService = (sender as MenuItem).Tag as DBLiveObject;
                        myDbService.Location = "R";
                        var n = Singleton<DB>.Instance.Commit();

                        // Refresh
                        this.ExecutionContextsRefreshCurrent();
                    });
            menuiteCreateRemoteDescriptor.Tag = dbService;
            menuiteCreateRemoteDescriptor.Enabled = false; // TODO when remote will be supported, reactivate this
            menuiteCreateDescriptor.MenuItems.Add(menuiteCreateRemoteDescriptor);

            serviceNode.ContextMenu.MenuItems.Add(menuiteCreateDescriptor);
        }

        /// <summary>
        /// The execution contexts_ build tree.
        /// </summary>
        /// <param name="ctx">
        /// The ctx.
        /// </param>
        /// <returns>
        /// </returns>
        private TreeNode ExecutionContextsBuildTree(DBExecutionContext ctx)
        {
            var nodeRoot = new TreeNode(string.Format("Execution Context \"{0}\"", ctx.Name));
            nodeRoot.ContextMenu = new ContextMenu();
#if ! DISABLE_NATIVE_CALLS
            var menuiteLauncherContext = new MenuItem(
                "Create Desktop Shortcut", 
                delegate(object sender, EventArgs args)
                    {
                        using (var shortcut = new ShellLink())
                        {
                            shortcut.Target = System.Windows.Forms.Application.ExecutablePath.ToLower().Replace("otadmui.exe", "OTCtlNC.exe");

                            // we use the non console version ot CommandLine Control
                            shortcut.Arguments = string.Format("executionContext run \"{0}\"", ctx.Name);
                            shortcut.WorkingDirectory = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
                            shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmMinimized;
                            shortcut.Description = "Bootstrap \"" + ctx.Name + "\"";
                            shortcut.Save(string.Format("{0}\\{1}.lnk", Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), ctx.Name));
                        }
                    });
            menuiteLauncherContext.Tag = ctx;
            nodeRoot.ContextMenu.MenuItems.Add(menuiteLauncherContext);
#endif

            var menuiteDuplicateContext = new MenuItem("Duplicate Context", delegate(object sender, EventArgs args) { });
            menuiteDuplicateContext.Tag = ctx;
            nodeRoot.ContextMenu.MenuItems.Add(menuiteDuplicateContext);
            menuiteDuplicateContext.Enabled = false; // TODO

            nodeRoot.ContextMenu.MenuItems.Add(new MenuItem("-"));

            var menuiteDestroyContext = new MenuItem(
                "Delete Context", 
                delegate(object sender, EventArgs args)
                    {
                        try
                        {
                            var myDbContext = (sender as MenuItem).Tag as DBExecutionContext;
                            DBExecutionContextHelpers.Destroy(myDbContext.ID);

                            // Refresh
                            this.ExecutionContextsRefreshList();
                        }
                        catch
                        {
                        }
                    });
            menuiteDestroyContext.Tag = ctx;
            nodeRoot.ContextMenu.MenuItems.Add(menuiteDestroyContext);

            var nodeContainers = new TreeNode("Containers");
            nodeContainers.ContextMenu = new ContextMenu();

            var menuiteContainer = new MenuItem(
                "Add Container (Safe Code) ...", 
                delegate(object sender, EventArgs args)
                    {
                        var ctrl = new UIGetText(
                            (object tsender, TextEventArgs targs) =>
                                {
                                    try
                                    {
                                        var container = DBContainer.CreateDBContainer(Guid.NewGuid(), targs.Text);
                                        container.IsStrong = false;
                                        ctx.DBContainer.Add(container);
                                        Singleton<DB>.Instance.Entities.AddToDBContainer(container);
                                        Singleton<DB>.Instance.Commit();

                                        // Inform the cache some newcome arrived
                                        this.containersCache.ContainerAdded(container.ID);

                                        this.ExecutionContextsRefreshCurrent();
                                    }
                                    catch
                                    {
                                    }
                                });

                        var form = ctrl.CreateContainingForm("Choose a name", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);
                        form.Visibility = EUIFormVisibility.ShowDialog;
                    });
            menuiteContainer.Tag = ctx;
            nodeContainers.ContextMenu.MenuItems.Add(menuiteContainer);

            var menuiteSafetyContainer = new MenuItem(
                "Add Strong Container (Unsafe Code) ...", 
                delegate(object sender, EventArgs args)
                    {
                        var ctrl = new UIGetText(
                            (object tsender, TextEventArgs targs) =>
                                {
                                    try
                                    {
                                        var container = DBContainer.CreateDBContainer(Guid.NewGuid(), targs.Text);
                                        container.IsStrong = true;
                                        ctx.DBContainer.Add(container);
                                        Singleton<DB>.Instance.Entities.AddToDBContainer(container);
                                        Singleton<DB>.Instance.Commit();

                                        // Inform the cache some newcome arrived
                                        this.containersCache.ContainerAdded(container.ID);

                                        this.ExecutionContextsRefreshCurrent();
                                    }
                                    catch
                                    {
                                    }
                                });

                        var form = ctrl.CreateContainingForm("Choose a name", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);
                        form.Visibility = EUIFormVisibility.ShowDialog;
                    });
            menuiteContainer.Tag = ctx;
            nodeContainers.ContextMenu.MenuItems.Add(menuiteSafetyContainer);

            foreach (var container in DBExecutionContextHelpers.GetContainers(ctx.ID, true))
            {
                var nodeContainerNode = new TreeNode(container.Name);
                nodeContainerNode.ContextMenu = new ContextMenu();
                nodeContainerNode.Tag = container.ID;

                if (container.IsStrong.HasValue && container.IsStrong.Value)
                {
                    nodeContainerNode.ImageIndex = 4;
                    nodeContainerNode.SelectedImageIndex = 4;
                }

                var menuiteTestContainer = new MenuItem(
                    "Test Container ...", 
                    delegate(object sender, EventArgs args)
                        {
                            // Guid id = (Guid)(sender as MenuItem).Tag;
                            // IResource[] resources = DBContainerHelpers.GetResources(id);
                            // if (Singleton<LiveObjectsRegistry>.Instance.CreateContainer(id, container.Name, resources, false))
                            // {
                            // ILiveObjectContainer lcontainer = Singleton<LiveObjectsRegistry>.Instance.GetContainer(id);
                            // UIIntrospectionReport ctrl = new UIIntrospectionReport(lcontainer, 20);
                            // UIForm form = ctrl.CreateContainingForm(string.Format("Live Object Container \"{0}\"", container.Name),
                            // EUIFormLayoutType.TitleBarAtTop,
                            // EUIFormClosingType.Hard);

                            // try
                            // {
                            // form.Visibility = EUIFormVisibility.ShowDialog;
                            // }
                            // catch (Exception e)
                            // {
                            // }

                            // Singleton<LiveObjectsRegistry>.Instance.DestroyContainer(id);
                            // }
                        });
                menuiteTestContainer.Tag = container.ID;
                nodeContainerNode.ContextMenu.MenuItems.Add(menuiteTestContainer);
                menuiteTestContainer.Enabled = false; // TODO

                nodeContainerNode.ContextMenu.MenuItems.Add(new MenuItem("-"));

                var menuiteDestroyContainer = new MenuItem(
                    "Delete Container", 
                    delegate(object sender, EventArgs args)
                        {
                            var lcontainer = (sender as MenuItem).Tag as DBContainer;

                            // Delete container (cascade)               
                            Singleton<DB>.Instance.Entities.DeleteObject(lcontainer);

                            // Save changes
                            var n = Singleton<DB>.Instance.Commit();

                            // Inform the cache some container was destroyed
                            this.containersCache.ContainerDeleted(container.ID);

                            Singleton<LiveObjectsRegistry>.Instance.DestroyContainer(container.ID);
                            this.ExecutionContextsRefreshCurrent();
                        });
                menuiteDestroyContainer.Tag = container;
                nodeContainerNode.ContextMenu.MenuItems.Add(menuiteDestroyContainer);
                if (container.Name.Equals("Default"))
                {
                    menuiteDestroyContainer.Enabled = false;
                }

                container.DBContainerResource.Load();
                foreach (var dbContainerResource in container.DBContainerResource)
                {
                    dbContainerResource.DBResourceReference.Load();
                    var nodeContainerresourceNode = new TreeNode(dbContainerResource.DBResource.Name);
                    nodeContainerresourceNode.ContextMenu = new ContextMenu();
                    nodeContainerresourceNode.ToolTipText = this.ExecutionContextsBuildContainerResourceTooltip(dbContainerResource);

                    var menuiteContainerRemoveResource = new MenuItem(
                        "Remove Resource", 
                        delegate(object sender, EventArgs args)
                            {
                                var parameters = (sender as MenuItem).Tag as object[];
                                var pcontainer = parameters[0] as DBContainer;
                                var presource = parameters[1] as DBContainerResource;

                                // Remove container resource from container
                                pcontainer.DBContainerResource.Remove(presource);

                                // Delete container resource
                                Singleton<DB>.Instance.Entities.DeleteObject(presource);

                                // Save changes
                                var n = Singleton<DB>.Instance.Commit();

                                // Inform the cache that some container was updated
                                this.containersCache.ContainerUpgraded(pcontainer.ID);

                                this.ExecutionContextsRefreshCurrent();
                            });
                    menuiteContainerRemoveResource.Tag = new object[] { container, dbContainerResource };
                    nodeContainerresourceNode.ContextMenu.MenuItems.Add(menuiteContainerRemoveResource);

                    nodeContainerNode.Nodes.Add(nodeContainerresourceNode);
                }

                nodeContainers.Nodes.Add(nodeContainerNode);
            }

            nodeRoot.Nodes.Add(nodeContainers);

            var nodeRuntime = new TreeNode("Runtime");
            nodeRuntime.ContextMenu = new ContextMenu();

            var dbApplication = DBExecutionContextHelpers.GetApplication(ctx.ID);
            if (dbApplication == null)
            {
                this.ExecutionContextsBuildApplicationNodeNewApplication(ctx, nodeRuntime);
            }
            else
            {
                this.ExecutionContextsBuildApplicationNodeExistingApplication(ctx, dbApplication, nodeRuntime);
            }

            nodeRoot.Nodes.Add(nodeRuntime);

            return nodeRoot;
        }

        /// <summary>
        /// The execution contexts_ edit memo.
        /// </summary>
        /// <param name="dbLiveObject">
        /// The dbLiveObject.
        /// </param>
        private void ExecutionContextsEditMemo(DBLiveObject dbLiveObject)
        {
            var ctrl = new UIGetText(
                dbLiveObject.Label, 
                (object tsender, TextEventArgs targs) =>
                    {
                        try
                        {
                            // Get the text
                            if (targs.Text != null && targs.Text.Length > 0)
                            {
                                dbLiveObject.Label = targs.Text;
                            }
                            else
                            {
                                dbLiveObject.Label = null;
                            }

                            // Save Changes
                            var n = Singleton<DB>.Instance.Commit();

                            // Refresh display
                            this.ExecutionContextsRefreshCurrent();
                        }
                        catch
                        {
                        }
                    });

            var form = ctrl.CreateContainingForm("Label", EUIFormLayoutType.TitleBarAtTop, EUIFormClosingType.Hard);
            form.Visibility = EUIFormVisibility.ShowDialog;
        }

        /// <summary>
        /// The execution contexts_ refresh current.
        /// </summary>
        private void ExecutionContextsRefreshCurrent()
        {
            this.dbContextByName = DBExecutionContextHelpers.GetExecutionContexts();
            var dbCtx = this.dbContextByName[this.comboboxExecutionContextEdit.Text];

            if (this.dbContextCurrent == null || dbCtx.Name != this.dbContextCurrent.Name)
            {
                this.dbContextCurrent = dbCtx;

                if (this.containersCache != null)
                {
                    this.containersCache.Dispose();
                }

                this.containersCache = new LiveObjectContainerCache(this.dbContextCurrent);
            }

            this.treeviewExecutionContexts.Nodes.Clear();
            this.treeviewExecutionContexts.Nodes.Add(this.ExecutionContextsBuildTree(this.dbContextCurrent));
            this.treeviewExecutionContexts.Sort();
            this.treeviewExecutionContexts.ExpandAll();
        }

        /// <summary>
        /// Refresh the execution control list
        /// </summary>
        private void ExecutionContextsRefreshList()
        {
            this.treeviewExecutionContexts.Nodes.Clear();
            this.comboboxExecutionContextEdit.Items.Clear();
            this.dbContextByName = DBExecutionContextHelpers.GetExecutionContexts();
            foreach (var v in this.dbContextByName.Values)
            {
                this.comboboxExecutionContextEdit.Items.Add(v.Name);
            }

            this.comboboxExecutionContextEdit.Enabled = this.comboboxExecutionContextEdit.Items.Count > 0;
        }

        /// <summary>
        /// The buttonExecutionContextCreate_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnButtonExecutionContextCreateClick(object sender, EventArgs e)
        {
            try
            {
                var ctxName = this.textBoxExecutionContextCreate.Text;

                DBExecutionContextHelpers.Create(ctxName);

                this.ExecutionContextsRefreshList();
                this.textBoxExecutionContextCreate.Clear();
                this.comboboxExecutionContextEdit.SelectedItem = ctxName;
            }
            catch
            {
            }
        }

        /// <summary>
        /// The comboboxExecutionContextEdit_ selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnComboboxExecutionContextEditSelectedIndexChanged(object sender, EventArgs e)
        {
            this.ExecutionContextsRefreshCurrent();
        }

        /// <summary>
        /// The textBoxExecutionContextCreate_ text changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnTextBoxExecutionContextCreateTextChanged(object sender, EventArgs e)
        {
            // If name is non empty and not already present in existing items list
            this.buttonExecutionContextCreate.Enabled = this.textBoxExecutionContextCreate.Text.Length > 0 &&
                                                        !this.comboboxExecutionContextEdit.Items.Contains(this.textBoxExecutionContextCreate.Text);
        }

        /// <summary>
        /// The treeviewExecutionContexts_ drag drop.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnTreeViewExecutionContextsDragDrop(object sender, DragEventArgs e)
        {
            var pos = this.treeviewExecutionContexts.PointToClient(new Point(e.X, e.Y));
            var targetNode = this.treeviewExecutionContexts.GetNodeAt(pos);

            if (targetNode == null)
            {
                return;
            }

            var droppedNode = e.Data.GetData(DataFormats.Serializable) as TreeNode;

            if (droppedNode == null)
            {
                return;
            }

            var containerName = targetNode.Text;
            var containerId = (Guid)targetNode.Tag;
            var dbContainer = DBContainerHelpers.GetContainer(containerId);

            var resourceDirectory = droppedNode.Tag as string;
            if (droppedNode.Tag == null)
            {
                // Resource (leaf)
                var resourcePath = PathUtil.Cleanup(droppedNode.FullPath, 1);
                var dbResource = DBResourceHelpers.GetResourceByPath(resourcePath);

                // Add the resource to a new DBContainerResource
                DBContainerResourceHelpers.Add(containerId, dbResource);
            }
            else
            {
                // Path (subtree)
                var resources = DBResourceHelpers.GetAllResourcesInDirectory(resourceDirectory);
                foreach (var dbResource in resources.Values)
                {
                    // Add the resource to a new DBContainerResource
                    DBContainerResourceHelpers.Add(containerId, dbResource);
                }
            }

            // Inform the cache that some container was updated
            this.containersCache.ContainerUpgraded(containerId);

            // Refresh the tree
            this.ExecutionContextsRefreshCurrent();
        }

        /// <summary>
        /// The treeviewExecutionContexts_ drag over.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnTreeViewExecutionContextsDragOver(object sender, DragEventArgs e)
        {
            var pos = this.treeviewExecutionContexts.PointToClient(new Point(e.X, e.Y));
            var targetNode = this.treeviewExecutionContexts.GetNodeAt(pos);

            if (targetNode != null && targetNode.FullPath.IndexOf("\\Containers\\") >= 0)
            {
                e.Effect = DragDropEffects.Link;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        /// <summary>
        /// The treeviewResources_ item drag.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void OnTreeViewResourcesItemDrag(object sender, ItemDragEventArgs e)
        {
            var targetNode = e.Item as TreeNode;
            this.DoDragDrop(targetNode, DragDropEffects.Link);
        }

        /// <summary>
        /// Build a Tree for assemblies, placing contect menus where needed
        /// </summary>
        /// <returns>
        /// </returns>
        private TreeNode ResourcesBuildTree()
        {
            var dbResources = DBResourceHelpers.GetAllResourcesInDirectory("\\");
            var root = new TreeNode("Available Resources");
            root.ContextMenu = new ContextMenu();

            // Setup the content
            foreach (var dbResource in dbResources.Values)
            {
                var dir = PathUtil.Cleanup(dbResource.Directory).Substring(1);
                var directoryNode = this.ResourcesCreateOrGetNode(dir, root, dbResource);

                var fileNode = new TreeNode(dbResource.Name);
                fileNode.Text = dbResource.Name;
                fileNode.Name = dbResource.Name;
                fileNode.ToolTipText = ResourcesBuildTooltip(dbResource);
                fileNode.ContextMenu = new ContextMenu();

                var deleteDistributionItem = new MenuItem(
                    "Delete", 
                    (object sender, EventArgs args) =>
                        {
                            var item = sender as MenuItem;
                            if (item != null)
                            {
                                var g = (Guid)item.Tag;
                                DBResourceHelpers.DestroyResources(g);

                                // Refresh view
                                this.ResourcesRefreshAll();
                            }
                        });

                deleteDistributionItem.Tag = dbResource.ID;

                fileNode.ContextMenu.MenuItems.Add(deleteDistributionItem);

                if (dbResource.IsAssembly)
                {
                    // Is marked as Code Assembly (loaded as assembly in the container)
                    fileNode.SelectedImageIndex = 1;
                    fileNode.ImageIndex = 1;

                    var menuiteContainerResourceUnmark = new MenuItem(
                        "UnMark as Code Assembly", 
                        delegate(object sender, EventArgs args)
                            {
                                var pdbresource = (sender as MenuItem).Tag as DBResource;
                                pdbresource.IsAssembly = false;
                                var n = Singleton<DB>.Instance.Commit();

                                // Refresh
                                this.ResourcesRefreshAll();
                            });
                    menuiteContainerResourceUnmark.Tag = dbResource;

                    fileNode.ContextMenu.MenuItems.Add(menuiteContainerResourceUnmark);
                }
                else if (dbResource.Extension.ToLower().CompareTo(".dll") == 0)
                {
                    // Is a dll and not marked as Code Assembly, offers the possibility 
                    var menuiteContainerResourceMark = new MenuItem(
                        "Mark as Code Assembly", 
                        delegate(object sender, EventArgs args)
                            {
                                var pdbresource = (sender as MenuItem).Tag as DBResource;
                                pdbresource.IsAssembly = true;
                                var n = Singleton<DB>.Instance.Commit();

                                // Refresh
                                this.ResourcesRefreshAll();
                            });
                    menuiteContainerResourceMark.Tag = dbResource;

                    fileNode.ContextMenu.MenuItems.Add(menuiteContainerResourceMark);
                }

                directoryNode.Nodes.Add(fileNode);
            }

            // #region MenuItem - Refresh Tree View + CallBack
            // MenuItem refreshAllItem = new MenuItem(
            // "Refresh TreeView ...",
            // (object sender, EventArgs args) =>
            // {
            // ResourcesRefreshAll();
            // });
            // #endregion
            // root.ContextMenu.MenuItems.Add(refreshAllItem);
            return root;
        }

        /// <summary>
        /// The resources_ create or get node.
        /// </summary>
        /// <param name="fullPath">
        /// The fullPath.
        /// </param>
        /// <param name="node">
        /// The node.
        /// </param>
        /// <param name="dbResource">
        /// The dbResource.
        /// </param>
        /// <returns>
        /// </returns>
        private TreeNode ResourcesCreateOrGetNode(string fullPath, TreeNode node, DBResource dbResource)
        {
            return this.ResourcesCreateOrGetNode(fullPath, string.Empty, node, dbResource);
        }

        /// <summary>
        /// The resources_ create or get node.
        /// </summary>
        /// <param name="relativePath">
        /// The relativePath.
        /// </param>
        /// <param name="fullPath">
        /// The fullPath.
        /// </param>
        /// <param name="node">
        /// The node.
        /// </param>
        /// <param name="dbResource">
        /// The dbResource.
        /// </param>
        /// <returns>
        /// </returns>
        private TreeNode ResourcesCreateOrGetNode(string relativePath, string fullPath, TreeNode node, DBResource dbResource)
        {
            // Terminal nodes
            if (relativePath == null)
            {
                return node;
            }

            string current = null;
            string under = null;
            var slash = relativePath.IndexOf("\\");
            if (slash > 0)
            {
                current = relativePath.Substring(0, slash);
                under = relativePath.Substring(slash + 1, relativePath.Length - slash - 1);
            }
            else
            {
                current = relativePath;
            }

            var nodes = node.Nodes.Find(current, false);
            TreeNode currentNode;
            if (nodes.Length == 1)
            {
                currentNode = nodes[0];
            }
            else
            {
                currentNode = new TreeNode(current);
                currentNode.Name = current;
                currentNode.Text = current;
                currentNode.Tag = fullPath + "\\" + current;
                node.Nodes.Add(currentNode);

                currentNode.ContextMenu = new ContextMenu();

                var importUpdateItem = new MenuItem(
                    "Import/Update Here ...", 
                    (object sender, EventArgs args) =>
                        {
                            var item = sender as MenuItem;
                            var directory = item.Tag as string;

                            // openfiledialog.InitialDirectory = "\\";
                            this.openfiledialog.Title = string.Format("Select resources to Import/Update under {0}", directory);
                            var r = this.openfiledialog.ShowDialog();
                            if (r == DialogResult.OK)
                            {
                                // Update
                                this.ResourcesRefreshAll();
                            }
                        });
                importUpdateItem.Tag = fullPath + "\\" + current;

                currentNode.ContextMenu.MenuItems.Add(importUpdateItem);

                var deleteDistributionItem = new MenuItem(
                    "Delete", 
                    (object sender, EventArgs args) =>
                        {
                            var item = sender as MenuItem;
                            if (item != null)
                            {
                                var dir = item.Tag as string;
                                DBResourceHelpers.DestroyResources(dir);

                                // Refresh view
                                this.ResourcesRefreshAll();
                            }
                        });
                deleteDistributionItem.Tag = fullPath + "\\" + current;

                currentNode.ContextMenu.MenuItems.Add(deleteDistributionItem);
            }

            return this.ResourcesCreateOrGetNode(under, fullPath + "\\" + current, currentNode, dbResource);
        }

        /// <summary>
        /// Redo the whole TreeView (Assemblies one)
        /// </summary>
        private void ResourcesRefreshAll()
        {
            this.treeviewResources.Nodes.Clear();
            this.treeviewResources.Nodes.Add(this.ResourcesBuildTree());
            this.treeviewResources.ExpandAll();
            this.treeviewResources.Sort();
        }

        /// <summary>
        /// A dirty thing to know how many tabs to add to align "Label       Value" correctly in tooltips
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <returns>
        /// The tabs.
        /// </returns>
        private string Tabs(string input)
        {
            var textSize = TextRenderer.MeasureText(input, this.treeviewExecutionContexts.Font);

            if (textSize.Width < 25)
            {
                return "\t\t\t\t";
            }

            if (textSize.Width < 50)
            {
                return "\t\t\t";
            }

            if (textSize.Width < 75)
            {
                return "\t\t";
            }

            return "\t";
        }

        #endregion
    }
}